#include "project.h"
#include <thread>
#include <atomic>

// ------------------------------ Device类实现 ------------------------------
Device::Device(string set_dev_path) : dev_path(set_dev_path) , fd(-1)
{
  if(this->open_dev() == false)
  {
    cout << "设备打开异常" << endl;
    exit(-1);
  }
}

bool Device::open_dev()
{
  if(this->fd != -1) 
  {
    cerr << "设备已打开" << endl;
    return false;
  }
  if((this->fd = open(this->dev_path.c_str(), O_RDWR)) == -1)
  {
    cerr << "设备打开失败" << strerror(errno) << endl;
    return false;
  }
  return true;
}

bool Device::close_dev()
{
  if(this->fd == -1) return true;
  if(close(this->fd) == -1)
  {
    cerr << "设备关闭失败" << strerror(errno) << endl;
    return false;
  }
  this->fd = -1;
  return true;
}

// ------------------------------ Lcd类实现 ------------------------------
Lcd::Lcd(string set_lcd_path) : Device(set_lcd_path)
{
  this->lcd_height = 0; 
  this->lcd_width = 0;
  this->mmap_start = nullptr;
  
  if(!this->mmap_lcd())
  {
    cout << "lcd映射异常" << endl;
    exit(-1);
  }
}

bool Lcd::mmap_lcd()
{
  //ioctl 获取lcd的宽高
  struct fb_var_screeninfo vinfo;
  memset(&vinfo, 0, sizeof(vinfo));//初始化结构体，防止脏数据
  if(ioctl(this->Device::fd, FBIOGET_VSCREENINFO, &vinfo) == -1)
  {
    cerr << "获取lcd宽高失败" << endl;
    return false;
  }

  this->lcd_height = vinfo.yres;
  this->lcd_width = vinfo.xres;

  //mmap映射
  this->mmap_start = (int *)mmap(
    NULL, 
    this->lcd_height * this->lcd_width * 4, 
    PROT_READ | PROT_WRITE, 
    MAP_SHARED, 
    this->Device::fd, 
    0
  );
  if(this->mmap_start == (int*)MAP_FAILED)
  {
    cerr << "lcd映射失败" << strerror(errno) << endl;
    return false;
  }

  return true;
}

bool Lcd::display_bmp(const char* bmp_path) {
    std::cout << "🔧 [display_bmp] 开始加载: " << bmp_path << std::endl;

    // 检查 mmap
    if (mmap_start == nullptr || mmap_start == MAP_FAILED) {
        std::cerr << "❌ [display_bmp] mmap_start 无效！" << std::endl;
        return false;
    }

    // 打开 BMP 文件
    int fd = open(bmp_path, O_RDONLY);
    if (fd == -1) {
        std::cerr << "❌ [display_bmp] 打开文件失败: " << strerror(errno) << std::endl;
        return false;
    }

    // ✅ 安全读取宽度和高度（小端序）
    unsigned char width_bytes[4], height_bytes[4];
    lseek(fd, 18, SEEK_SET);
    if (read(fd, width_bytes, 4) != 4 || read(fd, height_bytes, 4) != 4) {
        std::cerr << "❌ [display_bmp] 读取宽高失败" << std::endl;
        close(fd);
        return false;
    }

    int bmp_w = width_bytes[0] | (width_bytes[1] << 8) | (width_bytes[2] << 16) | (width_bytes[3] << 24);
    int bmp_h = height_bytes[0] | (height_bytes[1] << 8) | (height_bytes[2] << 16) | (height_bytes[3] << 24);

    bool top_down = false;
    if (bmp_h < 0) {
        bmp_h = -bmp_h;
        top_down = true;
    }

    std::cout << "✅ [display_bmp] BMP 尺寸: " << bmp_w << "x" << bmp_h 
              << (top_down ? " (Top-down)" : " (Bottom-up)") << std::endl;

    // 计算 padding
    int row_bytes = bmp_w * 3;
    int skip = (4 - (row_bytes % 4)) % 4;
    int line_bytes = row_bytes + skip;

    std::cout << "✅ [display_bmp] 每行字节数: " << line_bytes << " (skip=" << skip << ")" << std::endl;

    // 跳到像素数据
    lseek(fd, 54, SEEK_SET);

    // 读取像素数据
    char* buf = new (std::nothrow) char[static_cast<size_t>(line_bytes) * bmp_h];
    if (!buf) {
        std::cerr << "❌ [display_bmp] 内存分配失败" << std::endl;
        close(fd);
        return false;
    }

    if (read(fd, buf, line_bytes * bmp_h) != static_cast<ssize_t>(line_bytes * bmp_h)) {
        std::cerr << "❌ [display_bmp] 读取像素数据失败" << std::endl;
        delete[] buf;
        close(fd);
        return false;
    }

    // ✅ 清屏（可选）
    clearScreen();

    // ✅ 计算居中偏移（可扩展为 2/3 区域）
    int start_x = (lcd_width - bmp_w) / 2;
    int start_y = (lcd_height - bmp_h) / 2;

    std::cout << "📍 [display_bmp] 居中偏移: (" << start_x << ", " << start_y << ")" << std::endl;

    // 获取显存指针
    uint32_t* fb = reinterpret_cast<uint32_t*>(mmap_start);

    // ✅ 逐行处理
    for (int y = 0; y < bmp_h; y++) {
        // ✅ 正确处理 Top-down/Bottom-up
        int src_y = top_down ? y : (bmp_h - 1 - y);
        int src_offset = src_y * line_bytes;

        for (int x = 0; x < bmp_w; x++) {
            int src_pixel_offset = src_offset + x * 3;
            unsigned char b = buf[src_pixel_offset];
            unsigned char g = buf[src_pixel_offset + 1];
            unsigned char r = buf[src_pixel_offset + 2];

            // ✅ 颜色格式：RGB
            uint32_t color = (r << 16) | (g << 8) | b;

            // ✅ 计算 LCD 坐标
            int lcd_x = start_x + x;
            int lcd_y = start_y + y;

            // ✅ 边界检查
            if (lcd_x >= 0 && lcd_x < lcd_width && lcd_y >= 0 && lcd_y < lcd_height) {
                size_t index = static_cast<size_t>(lcd_y) * lcd_width + lcd_x;
                fb[index] = color;
            }
        }
    }

    std::cout << "✅✅✅ [display_bmp] 图片已显示完成！" << std::endl;

    delete[] buf;
    close(fd);
    return true;
}



void Lcd::clearScreen() 
{
  if (mmap_start == nullptr || mmap_start == (int*)MAP_FAILED) 
  {
    cerr << "LCD未正确映射（mmap_start无效）" << endl;
    return;
  }
  memset(mmap_start, 0, lcd_width * lcd_height * 4); // 清为黑色
}

Lcd::~Lcd()
{
  if(this->mmap_start != nullptr)
  {
    if(munmap(this->mmap_start, this->lcd_height * this->lcd_width * 4) == -1)
    {
      cout << "lcd映射关闭异常" << strerror(errno) << endl;
      exit(-1);
    }
    this->mmap_start = nullptr;
  }
  if(this->Device::close_dev() == false)
  {
    cout << "lcd设备关闭异常" << endl;
    exit(-1);
  }
}

// ------------------------------ Touch类实现 ------------------------------
static atomic<bool> is_listening(false); // 用于判断是否正在监听触摸事件
void Touch::addObserver(TouchObserver *observer)
{
  lock_guard<mutex> lock(mtx);
  if(observer != nullptr)
    this->observers.push_back(observer);
}

void Touch::removeObserver(TouchObserver *observer)
{
  lock_guard<mutex> lock(mtx);
  if(observer != nullptr)
  {
    auto it = find(this->observers.begin(), this->observers.end(), observer);
    if(it != this->observers.end())
      this->observers.erase(it);
  }

}

Touch::Touch(string set_touch_path) : Device(set_touch_path)
{
  this->touch_max_x = 1024;
  this->touch_max_y = 600;
  this->touch_min_x = 0;
  this->touch_min_y = 0;
  this->present_x = -1;
  this->present_y = -1;
}

bool Touch::Get_Click_Info(int timeout_ms) 
{
    struct input_event event;
    bool has_x = false, has_y = false;
    this->present_x = -1;
    this->present_y = -1;

    fd_set readfds;
    struct timeval tv;
    int max_fd = this->Device::fd + 1;

    // 用于检测“触摸开始”和“触摸结束”的标志
    bool touch_started = false;
    bool touch_ended = false;

    while (1) {
        FD_ZERO(&readfds);
        FD_SET(this->Device::fd, &readfds);

        if (timeout_ms >= 0) {
            tv.tv_sec = timeout_ms / 1000;
            tv.tv_usec = (timeout_ms % 1000) * 1000;
        }

        int ret = select(max_fd, &readfds, NULL, NULL, (timeout_ms >= 0) ? &tv : NULL);
        if (ret == -1) {
            if (errno == EINTR) continue;
            cerr << "Get_Click_Info: select error: " << strerror(errno) << endl;
            return false;
        } else if (ret == 0) {
            return false; // 超时
        }

        ssize_t len = read(this->Device::fd, &event, sizeof(event));
        if (len == 0) {
            cerr << "Get_Click_Info: 设备关闭" << endl;
            return false;
        }
        if (len != sizeof(event)) {
            cerr << "Get_Click_Info: 读取长度错误: " << len << endl;
            return false;
        }

        // 核心逻辑：通过 ABS_MT_POSITION_X/Y 的变化判断触摸状态
        if (event.type == EV_ABS) {
            if (event.code == ABS_MT_POSITION_X) {
                this->present_x = event.value;
                has_x = true;
                // X 坐标出现，视为触摸开始
                if (!touch_started) {
                    touch_started = true;
                    cout << "Get_Click_Info: 触摸开始 (X=" << event.value << ")" << endl;
                }
            } else if (event.code == ABS_MT_POSITION_Y) {
                this->present_y = event.value;
                has_y = true;
                // Y 坐标出现，视为触摸开始
                if (!touch_started) {
                    touch_started = true;
                    cout << "Get_Click_Info: 触摸开始 (Y=" << event.value << ")" << endl;
                }
            }
        } 
        // 关键：使用 ABS_MT_TRACKING_ID 来判断触摸点是否消失
        else if (event.type == EV_ABS && event.code == ABS_MT_TRACKING_ID) {
            if (event.value == -1) {
                // -1 通常表示触摸点被移除
                if (touch_started && !touch_ended) {
                    touch_ended = true;
                    cout << "Get_Click_Info: 触摸结束 (TRACKING_ID=-1)" << endl;
                }
            } else {
                // 新的触摸点
                touch_started = true;
                touch_ended = false;
            }
        }
        // 兜底：如果设备仍然发送 BTN_TOUCH，也处理
        else if (event.type == EV_KEY && event.code == BTN_TOUCH) {
            if (event.value == 0) {
                if (touch_started && !touch_ended) {
                    touch_ended = true;
                    cout << "Get_Click_Info: 触摸结束 (BTN_TOUCH=0)" << endl;
                }
            } else if (event.value == 1) {
                touch_started = true;
                touch_ended = false;
            }
        }
        // 在 SYN_REPORT 时检查是否完成了一次点击
        else if (event.type == EV_SYN && event.code == SYN_REPORT) {
            // 如果一次完整的触摸周期完成（开始 -> 结束）
            if (touch_started && touch_ended && has_x && has_y) {
                cout << "Get_Click_Info: 检测到点击 (" << present_x << ", " << present_y << ")" << endl;
                return true;
            }
            // 重置结束标志，等待下一次触摸结束
            if (touch_ended) {
                touch_ended = false;
            }
        }
    } // end while
    return false;
}


int Touch::Get_Swipe_Info(int timeout_ms) 
{
    struct input_event event;
    int start_x = -1, start_y = -1;
    int end_x = -1, end_y = -1;
    bool is_touching = false;
    const int SWIPE_THRESHOLD = 50;

    fd_set readfds;
    struct timeval tv;
    int max_fd = this->Device::fd + 1;

    while (1) {
        FD_ZERO(&readfds);
        FD_SET(this->Device::fd, &readfds);

        if (timeout_ms >= 0) {
            tv.tv_sec = timeout_ms / 1000;
            tv.tv_usec = (timeout_ms % 1000) * 1000;
        }

        int ret = select(max_fd, &readfds, NULL, NULL, (timeout_ms >= 0) ? &tv : NULL);
        if (ret == -1) {
            if (errno == EINTR) continue;
            cerr << "Get_Swipe_Info: select error: " << strerror(errno) << endl;
            return SWIPE_NONE;
        } else if (ret == 0) {
            return SWIPE_NONE; // 超时
        }

        ssize_t len = read(this->Device::fd, &event, sizeof(event));
        if (len == 0) {
            cerr << "Get_Swipe_Info: 设备关闭" << endl;
            return SWIPE_NONE;
        }
        if (len != sizeof(event)) {
            cerr << "Get_Swipe_Info: 读取长度错误: " << len << endl;
            return SWIPE_NONE;
        }

        // 核心：更健壮地处理触摸状态和坐标
        if (event.type == EV_KEY && event.code == BTN_TOUCH) {
            if (event.value == 1 && !is_touching) {
                is_touching = true;
                // 重置坐标，准备记录滑动
                start_x = -1; 
                start_y = -1;
                end_x = -1;
                end_y = -1;
                cout << "Get_Swipe_Info: 手指按下" << endl;
            } else if (event.value == 0 && is_touching) {
                is_touching = false;
                cout << "Get_Swipe_Info: 手指离开" << endl;
                break; // 准备判断滑动方向
            }
        } 
        else if (event.type == EV_ABS) {
            // 关键：确保在触摸状态下才记录坐标
            if (is_touching) {
                if (event.code == ABS_MT_POSITION_X) {
                    // 只要收到 X 坐标，就更新终点，并在第一次时设置起点
                    end_x = event.value;
                    if (start_x == -1) start_x = event.value;
                } else if (event.code == ABS_MT_POSITION_Y) {
                    end_y = event.value;
                    if (start_y == -1) start_y = event.value;
                }
                // 如果设备使用其他坐标码，也可以在这里添加
                // else if (event.code == ABS_X) { ... }
                // else if (event.code == ABS_Y) { ... }
            }
            // 注意：这里不再 break，而是继续循环读取，直到触摸结束
        }
        // 忽略 SYN_REPORT, ABS_MT_TRACKING_ID 等其他事件，它们不影响坐标采集
    } // end while(1)

    // 检查是否采集到了有效坐标
    if (start_x == -1 || start_y == -1 || end_x == -1 || end_y == -1) {
        cerr << "Get_Swipe_Info: 坐标数据不完整. Start(" 
             << start_x << "," << start_y << ") End(" << end_x << "," << end_y << ")" << endl;
        return SWIPE_NONE;
    }

    int delta_x = end_x - start_x;
    int delta_y = end_y - start_y;
    int abs_delta_x = abs(delta_x);
    int abs_delta_y = abs(delta_y);

    cout << "Swipe: Start(" << start_x << "," << start_y << ") -> End(" 
         << end_x << "," << end_y << ") Delta=(" << delta_x << "," << delta_y << ")" << endl;

    if (abs_delta_x > SWIPE_THRESHOLD && abs_delta_x > abs_delta_y) {
        return (delta_x > 0) ? SWIPE_RIGHT : SWIPE_LEFT;
    } else if (abs_delta_y > SWIPE_THRESHOLD && abs_delta_y > abs_delta_x) {
        return (delta_y > 0) ? SWIPE_DOWN : SWIPE_UP;
    } else {
        return SWIPE_NONE; // 滑动距离太短，视为无效
    }
}

void Touch::notifyClick(int x, int y)
{
  lock_guard<mutex> lock(mtx);
  cout << "notifyClick" << endl;
  for(auto observer : this->observers)
  {
    observer->onTouchClick(x, y);
  }

  cout << "notifyClick end" << endl;
}

void Touch::notifySwipe(int swipe_direction)
{
  lock_guard<mutex> lock(mtx);

  cout << "notifySwipe" << endl;
  for(auto observer : this->observers)
  {
    observer->onTouchSwipe(swipe_direction);
  }

  cout << "notifySwipe end" << endl;
}

 void Touch::startListening() {
        if (is_listening.load() || listener_thread.joinable()) {
            cout << "❌ Touch: 监听已启动或线程已存在，忽略重复启动" << endl;
            return;
        }
        is_listening.store(true);

        listener_thread = std::thread([this]() {
            struct input_event event;
            fd_set readfds;
            int max_fd = this->Device::fd + 1;

            cout << "✅ Touch: 监听线程已启动，开始读取设备事件..." << endl;

            try {
                while (is_listening.load()) {
                    FD_ZERO(&readfds);
                    FD_SET(this->Device::fd, &readfds);

                    struct timeval tv = {0, 10000}; // 10ms 超时
                    int ret = select(max_fd, &readfds, NULL, NULL, &tv);

                    if (ret == -1) {
                        if (errno == EINTR) continue;
                        cerr << "❌ Touch listener select error: " << strerror(errno) << endl;
                        break;
                    } else if (ret == 0) {
                        continue; // 超时，继续循环
                    }

                    // 有数据可读
                    ssize_t len = read(this->Device::fd, &event, sizeof(event));
                    if (len != sizeof(event)) {
                        if (len == 0) {
                            cerr << "❌ Touch device closed." << endl;
                        } else {
                            cerr << "❌ Read error or partial read: " << len << endl;
                        }
                        break;
                    }

                    // === 调试：打印原始事件 ===
                    cout << "[DEBUG] Raw Event: type=" << event.type << ", code=" << event.code 
                         << ", value=" << event.value << ", time=" << event.time.tv_sec 
                         << "." << event.time.tv_usec << endl;

                    // === 事件分发逻辑 ===
                    if (event.type == EV_KEY) {
                        if (event.code == BTN_TOUCH || event.code == BTN_TOOL_FINGER) {
                            if (event.value == 1) {
                                // 手指按下
                                cout << "✅ 手指按下 (BTN_TOUCH/BTN_TOOL_FINGER)" << endl;
                                is_touching = true;
                                start_x = -1; // 重置起点
                                start_y = -1;
                                current_x = -1;
                                current_y = -1;
                            } else if (event.value == 0) {
                                // 手指离开
                                cout << "✅ 手指离开 (BTN_TOUCH/BTN_TOOL_FINGER)" << endl;

                                if (is_touching && current_x != -1 && current_y != -1) {
                                    // 判断是点击还是微小移动
                                    if (start_x != -1 && start_y != -1) {
                                        int dx = abs(current_x - start_x);
                                        int dy = abs(current_y - start_y);
                                        const int CLICK_THRESHOLD = 20; // 像素

                                        cout << "🔍 释放时坐标: start=(" << start_x << "," << start_y 
                                             << ") current=(" << current_x << "," << current_y 
                                             << ") dx=" << dx << ", dy=" << dy 
                                             << ", 阈值=" << CLICK_THRESHOLD << endl;

                                        if (dx < CLICK_THRESHOLD && dy < CLICK_THRESHOLD) {
                                            // 视为点击
                                            int lcd_x = mapToLcdX(current_x);
                                            int lcd_y = mapToLcdY(current_y);
                                            cout << "🎯 检测到点击! 原始(" << current_x << "," << current_y 
                                                 << ") -> 映射(" << lcd_x << "," << lcd_y << ")" << endl;
                                            
                                            // 通知观察者
                                            notifyClick(lcd_x, lcd_y);
                                            
                                            // 设置事件状态供 Get_Click_Info 使用
                                            {
                                                lock_guard<mutex> lock(event_mutex);
                                                last_event_type = CLICK;
                                                last_click_x = lcd_x;
                                                last_click_y = lcd_y;
                                                event_ready = true;
                                                event_cv.notify_all();
                                            }
                                        } else {
                                            // 视为滑动
                                            int dir = SWIPE_NONE;
                                            if (dx > dy && dx > CLICK_THRESHOLD) {
                                                dir = (current_x > start_x) ? SWIPE_RIGHT : SWIPE_LEFT;
                                            } else if (dy > dx && dy > CLICK_THRESHOLD) {
                                                dir = (current_y > start_y) ? SWIPE_DOWN : SWIPE_UP;
                                            }
                                            if (dir != SWIPE_NONE) {
                                                cout << "➡️  检测到滑动: 方向=" << dir << endl;
                                                // 通知观察者
                                                notifySwipe(dir);
                                                
                                                // 设置事件状态供 Get_Swipe_Info 使用
                                                {
                                                    lock_guard<mutex> lock(event_mutex);
                                                    last_event_type = SWIPE;
                                                    last_swipe_dir = dir;
                                                    event_ready = true;
                                                    event_cv.notify_all();
                                                }
                                            }
                                        }
                                    } else {
                                        cout << "⚠️  释放时缺少起点坐标，无法判断点击/滑动" << endl;
                                    }
                                } else {
                                    cout << "⚠️  释放时缺少当前坐标，无法判断点击/滑动" << endl;
                                }

                                // 重置状态
                                is_touching = false;
                                start_x = -1;
                                start_y = -1;
                            }
                        }
                    }
                    else if (event.type == EV_ABS) {
                        // 处理触摸坐标（支持多种协议）
                        bool coord_updated = false;
                        if (event.code == ABS_MT_POSITION_X || event.code == ABS_X) {
                            current_x = event.value;
                            coord_updated = true;
                            cout << "📍 X坐标更新: " << event.value << endl;
                            // 记录第一次触摸的 X 作为起点
                            if (is_touching && start_x == -1) {
                                start_x = event.value;
                                cout << "📍 记录起点X: " << start_x << endl;
                            }
                        } else if (event.code == ABS_MT_POSITION_Y || event.code == ABS_Y) {
                            current_y = event.value;
                            coord_updated = true;
                            cout << "📍 Y坐标更新: " << event.value << endl;
                            // 记录第一次触摸的 Y 作为起点
                            if (is_touching && start_y == -1) {
                                start_y = event.value;
                                cout << "📍 记录起点Y: " << start_y << endl;
                            }
                        }
                        
                        // 其他可能的坐标码
                        if (event.code == ABS_MT_TRACKING_ID) {
                            cout << "📍 MT Tracking ID: " << event.value << endl;
                        }
                        if (event.code == ABS_PRESSURE) {
                            cout << "📍 压力: " << event.value << endl;
                        }
                    }
                    // 忽略 SYN_REPORT 等同步事件（它们只表示事件块结束）

                } // end while(is_listening)

            } catch (...) {
                cerr << "❌ Touch listener thread exception" << endl;
            }

            cout << "✅ Touch listener stopped." << endl;
        });
    }

void Touch::stopListening() 
{
    // 1. 设置停止标志
    is_listening.store(false);
    std::cout << "正在请求停止触摸监听..." << std::endl;

    // 2. 等待线程结束
    if
 (listener_thread.joinable()) {
        listener_thread.join(); // 阻塞直到线程函数执行完毕
        std::cout << "触摸监听已停止。" << std::endl;
    } else
 {
        std::cout << "触摸监听线程不可连接（可能未启动或已停止）" << std::endl;
    }
}

Touch::~Touch() {
    stopListening(); // 确保线程已停止
    // Device 析构会关闭 fd
}

int Touch::mapToLcdX(int touch_x) {
    // 线性映射： new_x = (old_x - min_x) * (lcd_max - lcd_min) / (touch_max - touch_min) + lcd_min
    // 假设 LCD 宽度为 800, 高度为 480
    const int LCD_WIDTH = 1024;
    const int LCD_HEIGHT = 600;

    if (this->touch_max_x <= this->touch_min_x) return 0;
    
    int lcd_x = (touch_x - this->touch_min_x) * LCD_WIDTH / (this->touch_max_x - this->touch_min_x);
    // 限制在 LCD 范围内
    if (lcd_x < 0) lcd_x = 0;
    if (lcd_x >= LCD_WIDTH) lcd_x = LCD_WIDTH - 1;
    return lcd_x;
}


int Touch::mapToLcdY(int touch_y) {
    const int LCD_WIDTH = 1024;
    const int LCD_HEIGHT = 600;

    if (this->touch_max_y <= this->touch_min_y) return 0;
    
    int lcd_y = (touch_y - this->touch_min_y) * LCD_HEIGHT / (this->touch_max_y - this->touch_min_y);
    if (lcd_y < 0) lcd_y = 0;
    if (lcd_y >= LCD_HEIGHT) lcd_y = LCD_HEIGHT - 1;
    return lcd_y;
}




